package ch.epfl.sdp.database.dao

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import ch.epfl.sdp.database.data.SearchGroupData
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase

class FirebaseGroupDao : SearchGroupDao {

    companion object {
        private const val ROOT_PATH = "search_groups"
    }

    private var database: FirebaseDatabase = Firebase.database

    private val groups: MutableLiveData<List<SearchGroupData>> = MutableLiveData(listOf())
    private val watchedGroupsByGroupId: MutableMap<String, MutableLiveData<SearchGroupData>> = mutableMapOf()

    override fun getGroups(): LiveData<List<SearchGroupData>> {
        val myRef = database.getReference(ROOT_PATH)
        myRef.addValueEventListener(object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                groups.value = (dataSnapshot.children.map { c ->
                    // Get group data (without key)
                    val group = c.getValue(SearchGroupData::class.java)
                    // Retrieve group key generated by google and use it
                    group?.uuid = c.key
                    group!!
                })
            }

            override fun onCancelled(error: DatabaseError) {
                // Failed to read value
                Log.w("Firebase", "Failed to read value.")
            }
        })
        return groups
    }

    override fun getGroupById(groupId: String): LiveData<SearchGroupData> {
        if (!watchedGroupsByGroupId.containsKey(groupId)) {
            val myRef = database.getReference("$ROOT_PATH/$groupId")
            watchedGroupsByGroupId[groupId] = MutableLiveData()
            //TODO change to childEventListener ?
            myRef.addValueEventListener(object : ValueEventListener {
                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    val group = dataSnapshot.getValue(SearchGroupData::class.java)
                    group?.uuid = dataSnapshot.key
                    watchedGroupsByGroupId[groupId]!!.value = group
                }

                override fun onCancelled(error: DatabaseError) {
                    Log.w("Firebase", "Failed to read group from firebase.")
                }
            })
        }
        return watchedGroupsByGroupId[groupId]!!
    }

    /**
     * Creates a group with the given data.
     * The uuid of the searchgroup data will be overridden by an automatically generated one.
     */
    override fun createGroup(searchGroupData: SearchGroupData): String {
        val key = database.getReference(ROOT_PATH).push().key
        database.getReference("$ROOT_PATH/$key").setValue(searchGroupData)
        return key!!
    }

    override fun updateGroup(searchGroupData: SearchGroupData) {
        database.getReference("$ROOT_PATH/${searchGroupData.uuid}").setValue(searchGroupData)
    }

    override fun removeSearchGroup(searchGroupId: String) {
        database.getReference("$ROOT_PATH/${searchGroupId}").removeValue()
    }
}